-
Notifications
You must be signed in to change notification settings - Fork 13.5k
take into account the num of processes by ulimit #143614
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
@@ -440,13 +440,24 @@ pub fn available_parallelism() -> io::Result<NonZero<usize>> { | |||
} | |||
} | |||
} | |||
|
|||
let mut ulimit = u64::MAX; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The type is rlim_t
, this won't work on x86-32
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
#[cfg(any(target_os = "android", target_os = "linux"))] | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The above block has the same cfg
, this can be combined
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
Could you please put a more detailed description of how the problem is reproduced in the PR description? Or open a separate issue for it. The change here also needs comments, and the docs at https://doc.rust-lang.org/beta/std/thread/fn.available_parallelism.html should be updated if this winds up being accepted. Since this is a user-visible change this will need t-libs signoff, but first cc @cuviper since it looks like the issue shows up in Rayon (possibly rayon-rs/rayon#694?) |
This comment has been minimized.
This comment has been minimized.
I doubt that this will be useful -- e.g. starting a number of threads equal to the current |
let mut r: libc::rlimit = unsafe { mem::zeroed() }; | ||
unsafe { | ||
if libc::getrlimit(libc::RLIMIT_NPROC, &mut r) == 0 { | ||
ulimit = r.rlim_max |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note, the "soft" rlim_cur
is the value that is currently enforced, while the "hard" rlim_max
is a limit on how high an unprivileged process can adjust its own rlim_cur
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
I see, patchset updated according this comment (will count working threads) |
be59dbd
to
65b3d80
Compare
bug here: rust-lang/rustup#4403 |
This comment has been minimized.
This comment has been minimized.
This makes it possible, as long as nothing else starts in the meantime, but I still don't think it's a good idea for a threadpool to completely and greedily claim the entire thread limit. (I also replied in rust-lang/rustup#4403 (comment).) It would be better to set a limit like Fundamentally, these resource limits are quite different than the basic "number of logical CPUs" view of available parallelism, because it's not really a problem to oversubscribe CPUs. |
this patchset is not about 'greedily claim', here we are just return number of available parallel tasks anyway, I just want to help and show the problem, if you think that this issue is not "big deal" - ok, I just close request |
This comment has been minimized.
This comment has been minimized.
Please understand, I did not mean any judgement in calling it "greedy". It is the documented expectation of
I am just one voice here -- it's possible that other team members may feel differently. |
due to ulimit restrictions is not used in std::thread upears crashed like this one: thread 'main' panicked at .../.cargo/registry/.../rayon-core-1.12.1/src/registry.rs:168:10: The global thread pool has not been initialized.: ThreadPoolBuildError { kind: IOError(Os { code: 11, kind: WouldBlock, message: "Resource temporarily unavailable" }) } resolve #143635
I'm not sure what would be best here so |
from the rustup issue:
nproc counts per-user threads, so it's a shared cap. An individual process can't really account for that and
I.e. won't look at what other processes are doing. Maybe we can do something conservative here, if something sets a ridiculously tight nproc limit (<= number of CPUs) then we just clamp parallelism to 1 because we don't know what else might be running under that UID and we don't want to eat up all the threads. Or maybe rayon should have a limited-effort mode where it spawns threads if it can but doesn't explode when the system doesn't let it. |
one more issue related to wrong behavior of std::thread::available_parallelism in Linux systems with ulimit restrictions: |
We discussed this in the @rust-lang/libs meeting. There are many reasons why thread creation may fail, and fundamentally @rfcbot close |
Team member @Amanieu has proposed to close this. The next step is review by the rest of the tagged team members: No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
For example, this could be similar to |
I glad to listen that you drew attention to the problem
|
Your use-case is uncommon, that is not sufficient motivation to deprecate an existing, widely-used std API. Software looking at cpumasks, cgroups and number of processor cores and then returning the minimum of that is common practice. Java, C#, C++ all do some of that. None of them look at nprocs. That is because nprocs is commonly set to a much larger number, and when it is limited it is really difficult to account for because it's shared across processes. It's more like running out of disk space.... you only notice when you hit the limit. Using nprocs to limit shared workloads feels like a technique from the 90s. It's fine if you're running a bunch bunch of php or perl scripts or whatever. It doesn't interact well with modern multi-threaded runtimes. One can write Rust like that, but most projects don't default to few-/single-threaded behavior and you have to explicitly opt in to that via arguments or environment variables. I think adding an override for std would be reasonable since it'll avoid having to tweak things for each crate separately. |
No description provided.